package com.ksyun.alert.filter;

import com.ksyun.alert.utils.RequestIpUtil;
import com.ksyun.alert.utils.RequestIdUtil;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 请求过滤器
 * @author: hantou
 * @date: 2024-05-01
 */
@Component
public class RequestFilter extends OncePerRequestFilter {

    // 请求白名单，暂未配置
    @Value("not set yet...")
    private static final List<String> filterUrls = new ArrayList<>();

    public static final String TRACE_KEY = "requestId";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if(this.isIgnoreUrl(request.getServletPath())){
            filterChain.doFilter(request, response);
        }else {
            try{
                RequestIdUtil.generateRequestId();
                RequestIpUtil.setRequestId(request.getRemoteAddr());
                String requestId = RequestIdUtil.getRequestId();
                MDC.put(TRACE_KEY, requestId);
                filterChain.doFilter(request, response);
            } finally {
                RequestIpUtil.removeRequestIp();
                RequestIdUtil.removeRequestId();
                resetContextHolders();
            }

        }
    }

    /**
     * 判定当前请求url是否不需要过滤
     * @param url 路径
     * @return 是否忽略
     */
    private boolean isIgnoreUrl(String url){
        if(Objects.isNull(filterUrls)){
            return false;
        }
        for (String ignore : filterUrls) {
            if(url.startsWith(ignore)) return true;
        }
        return false;
    }

    /**
     * 清空MDC
     */
    private void resetContextHolders() {
        MDC.remove(TRACE_KEY);
    }
}
